package wrm.saferJava.aop;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import wrm.saferJava.oval.guard.Guarded;
import wrm.saferJava.oval.internal.util.ReflectionUtils;

public class GuardClassInjector implements ClassVisitor, Opcodes {

	ClassVisitor writer;
	ClassLoader loader;
	
	boolean isGuardedClass = false;
	private String curClass;
	private boolean isInterface;
	
	
	public GuardClassInjector(ClassVisitor writer, ClassLoader loader) {
		super();
		this.writer = writer;
		this.loader = loader;		
	}
	public void visit(int version, int access, String name, String desc,
			String superType, String[] interfaces) {
		writer.visit(version, access, name, desc, superType, interfaces);
		

		
		curClass = name;
		isInterface = (access & ACC_INTERFACE) > 0;
		
		//recursive load referenced classes first (supertype and interfaces)
		//so we are able to determine, if a superclass or interface is annotated with "Guarded"
		if (!isInterface)
		{
			try {
				Class superClass = loader.loadClass(superType.replace('/', '.'));
				isGuardedClass = superClass.isAnnotationPresent(Guarded.class);
			
				//inspect interfaces
				if (!isGuardedClass)
					for(String i : interfaces)
					{
						Class interfaceClass = loader.loadClass(i.replace('/', '.'));
						isGuardedClass = interfaceClass.isAnnotationPresent(Guarded.class);
						if (isGuardedClass)
							break;
					}
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
	}
	public AnnotationVisitor visitAnnotation(String desc, boolean arg1) {
		if (!isGuardedClass
				&& !isInterface
				&& desc.equals("L" + Type.getInternalName(Guarded.class) + ";"))
			isGuardedClass = true;
		
		return writer.visitAnnotation(desc, arg1);
	}
	public void visitAttribute(Attribute arg0) {
		writer.visitAttribute(arg0);
	}
	public void visitEnd() {
		writer.visitEnd();
	}
	public FieldVisitor visitField(int arg0, String arg1, String arg2,
			String arg3, Object arg4) {
		return writer.visitField(arg0, arg1, arg2, arg3, arg4);
	}
	public void visitInnerClass(String arg0, String arg1, String arg2, int arg3) {
		writer.visitInnerClass(arg0, arg1, arg2, arg3);
	}
	public MethodVisitor visitMethod(int arg0, String arg1, String arg2,
			String arg3, String[] arg4) {
		return writer.visitMethod(arg0, arg1, arg2, arg3, arg4);
	}
	public void visitOuterClass(String arg0, String arg1, String arg2) {
		writer.visitOuterClass(arg0, arg1, arg2);
	}
	public void visitSource(String arg0, String arg1) {
		writer.visitSource(arg0, arg1);
	}

	public boolean isGuardedClass() {
		return isGuardedClass;
	}
	public String getCurClass() {
		return curClass;
	}
}
